package com.xh.sso.server.authentiation.oauth2.support.request;


import com.alibaba.fastjson.JSONObject;
import com.xh.security.core.authentiation.oauth2.support.config.AuthConfig;
import com.xh.security.core.authentiation.oauth2.support.enums.AuthUserGender;
import com.xh.security.core.authentiation.oauth2.support.exception.AuthException;
import com.xh.security.core.authentiation.oauth2.support.model.AuthCallback;
import com.xh.security.core.authentiation.oauth2.support.model.AuthToken;
import com.xh.security.core.authentiation.oauth2.support.model.AuthUser;
import com.xh.security.core.authentiation.oauth2.support.request.AuthDefaultRequest;
import com.xh.security.core.utils.cache.AuthCache;
import com.xh.sso.server.authentiation.oauth2.support.config.AuthSsoSource;
import com.xkcoding.http.HttpUtil;
import com.xkcoding.http.support.HttpHeader;
import org.apache.commons.codec.binary.Base64;

import java.nio.charset.Charset;

/**
 * 系统内部sso单点登录
 */
public class AuthSsoRequest extends AuthDefaultRequest {

    public AuthSsoRequest(AuthConfig config, AuthCache authCache) {
        super(config, AuthSsoSource.SSO, authCache);
    }

    @Override
    public AuthToken getAccessToken(AuthCallback authCallback) {
        String response = doPostAuthorizationCode(authCallback.getCode());
        JSONObject accessTokenObject = JSONObject.parseObject(response);
        this.checkResponse(accessTokenObject);
        return AuthToken.builder()
            .accessToken(accessTokenObject.getString("access_token"))
            .refreshToken(accessTokenObject.getString("refresh_token"))
            .scope(accessTokenObject.getString("scope"))
            .tokenType(accessTokenObject.getString("token_type"))
            .expireIn(accessTokenObject.getIntValue("expires_in"))
            .build();
    }

    @Override
    protected String doPostAuthorizationCode(String code) {
        HttpHeader header = new HttpHeader();
        header.add("Authorization", getHeader(config.getClientId(), config.getClientSecret()));
        return HttpUtil.post(accessTokenUrl(code), null, header);
    }

    private String getHeader(String clientId, String secretId) {
        String auth = clientId + ":" + secretId;
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("UTF-8")));
        return "Basic " + new String(encodedAuth);
    }

    @Override
    protected AuthUser getUserInfo(AuthToken authToken) {
        String userInfo = doGetUserInfo(authToken);
        JSONObject object = JSONObject.parseObject(userInfo);
        this.checkResponse(object);
        return AuthUser.builder()
            .uuid(object.getString("id"))
            .username(object.getString("login"))
            .avatar(object.getString("avatar_url"))
            .blog(object.getString("blog"))
            .nickname(object.getString("name"))
            .company(object.getString("company"))
            .location(object.getString("address"))
            .email(object.getString("email"))
            .remark(object.getString("bio"))
            .gender(AuthUserGender.UNKNOWN)
            .token(authToken)
            .source(source.toString())
            .build();
    }

    /**
     * 检查响应内容是否正确
     *
     * @param object 请求响应内容
     */
    private void checkResponse(JSONObject object) {
        if (object.containsKey("error")) {
            throw new AuthException(object.getString("error_description"));
        }
    }
}
